<template>
    <el-card v-if="!isShowMap" class="fatherBox">
        <div class="headerBox">
            <span class="title">{{ imageInfo.picName }}</span>
            <el-button type="primary" class="btn1" @click="showMap">选择地图</el-button>
            <el-button class="btn2" @click="clearPoint">清空当前点位</el-button>
        </div>
        <div class="contentBox">
            <div class="content-left">
                <div class="left-header">
                    <SyRadio v-model="selRadio" :data="selRadioList" />
                    <el-input class="left-header-input" v-model="searchInput" placeholder="请输入" :suffix-icon="Search"
                        @keydown.enter="searchTree" clearable></el-input>
                </div>
                <div class="left-content">
                    <el-tree :class="['aside_tree', { 'hide': !showTree }]" :key="treeKey" node-key="id"
                        :props="defaultProps" highlight-current="true" ref="asideElTree"
                        @node-click="handleOrgTreeNodeClick" lazy :load="loadNode">
                        <template #default="{ node, data }">
                            <!-- :draggable="data.placeType == 'point' && !allPoints.map((item: any) => item.pointId).includes(data.id)" -->
                            <span class="custom-tree-node" ref="externalPointRef"
                                @dragstart="handleDragStart($event, data)" @dragend="handleDragEnd($event, data)">
                                <img v-if="data.placeType == 'point' && data.pointType == '1'" :src="camera" />
                                <img v-else-if="data.placeType == 'point' && data.pointType == '2'" :src="accessLogo" />
                                <img v-else-if="data.placeType == 'point' && data.pointType == '3'" :src="otherList" />
                                <span v-if="data.placeType !== 'point'" style="padding: 0 9px 0 16px;">{{ node.label
                                }}</span>
                                <span v-else style="padding: 0 9px 0 16px;">{{ data.pointName }}</span>
                                <span v-if="data.userCount != 0 && data.placeType == 'region'">（{{ data.userCount
                                }}）</span>
                                <img v-if="data.placeType == 'point'" :src="position" />
                            </span>
                        </template>
                    </el-tree>
                    <el-tree v-if="!showTree" class="aside_tree" node-key="id"
                        style="max-height: calc(100vh - 315px); overflow: auto" :data="leftTree" :props="defaultProps"
                        highlight-current="true" ref="asideElTree1" @node-click="handleOrgTreeNodeClick">
                        <template #default="{ node, data }">
                            <span class="custom-tree-node">
                                <img v-if="data.placeType == 'point' && data.pointType == '1'" :src="camera" />
                                <img v-else-if="data.placeType == 'point' && data.pointType == '2'" :src="accessLogo" />
                                <img v-else-if="data.placeType == 'point' && data.pointType == '3'" :src="otherList" />
                                <span v-if="data.placeType !== 'point'" style="padding: 0 9px 0 16px;">{{ node.label
                                }}</span>
                                <span v-else style="padding: 0 9px 0 16px;">{{ data.pointName }}</span>
                                <span v-if="data.userCount != 0 && data.placeType == 'region'">（{{ data.userCount
                                }}）</span>
                                <img v-if="data.placeType == 'point'" :src="position" />
                            </span>
                        </template>
                    </el-tree>
                </div>
            </div>
            <div class="content-right">
                <canvas ref="canvasRef" width="1394" height="740"></canvas>
                <div class="groupBtn">
                    <el-button class="btn1" @click="locate"><img :src="locate1" /></el-button>
                    <el-button-group class="btns2">
                        <el-button @click="zoomIn"><img :src="add" /></el-button>
                        <div class="line"></div>
                        <el-button @click="zoomOut"><img :src="reduce" /></el-button>
                    </el-button-group>
                </div>
            </div>
        </div>
    </el-card>
    <SelMap v-else ref="selCamera" />
</template>

<script setup lang="ts">
import SyRadio from './SyRadio/index.vue'
import { buildTree } from './utils/secTreeNum'
import { onMounted, provide, ref, watch } from 'vue';
import { Search } from '@element-plus/icons-vue'
// import { GetRigionTreeList, GetMap, GetAllPoints, AddPoint, ClearPoint, DelPoint } from '@/api/space/map';
import camera from '@/assets/images/space/camera.png'
import accessLogo from '@/assets/images/space/accessLogo.png'
import position from '@/assets/images/space/position.png'
import locate1 from '@/assets/images/space/locate.png'
import add from '@/assets/images/space/add.png'
import reduce from '@/assets/images/space/reduce.png'
import type Node from 'element-plus/es/components/tree/src/model/node'
// import SelMap from './selMap.vue'
import map from '@/assets/images/space/map.png'
import deleteIcon from '@/assets/images/space/deleteIcon.png';
import point from '@/assets/images/space/point.png';
import pointBlue from '@/assets/images/space/pointBlue.png';
import access from '@/assets/images/space/access.png';
import accessBlue from '@/assets/images/space/accessBlue.png';
import otherGray from '@/assets/images/space/otherGray.png';
import otherBlue from '@/assets/images/space/otherBlue.png';
import otherList from '@/assets/images/space/otherList.png';
import { ElMessage } from 'element-plus';
// 测试数据
let ceshiData: any = ref({
    regionList: [
        {
            "total": 0,
            "createBy": "admin",
            "createTime": "2024-12-11 13:47:58",
            "updateBy": "",
            "updateTime": "",
            "id": "ffa07cff12226ab5811f44693d51ebeb",
            "name": "小会议室",
            "fullName": "湘云大学/大门/小会议室",
            "description": "",
            "parentId": "8ca8131707c3821645a14f6f19247370",
            "regionLevel": "3",
            "leader": "",
            "sortNo": "",
            "regionType": "1",
            "codeNo": "",
            "roomType": "",
            "campusId": "",
            "parkId": "",
            "functionType": "",
            "longitude": "",
            "latitude": "",
            "planId": "",
            "buildNo": "",
            "floorNo": "",
            "status": "1",
            "openStatus": "2",
            "indexFloor": "",
            "floorCount": "",
            "roomCount": "",
            "label": "",
            "pointName": "",
            "floorCode": "",
            "departId": "",
            "roleId": "",
            "departName": "",
            "openState": "",
            "sections": "",
            "strategyType": "",
            "needRecover": "",
            "managerCount": "",
            "userCount": "",
            "leaf": false
        },
        {
            "total": 0,
            "createBy": "admin",
            "createTime": "2024-12-11 13:48:19",
            "updateBy": "",
            "updateTime": "",
            "id": "7d90e6ac5b3bf9d249c030f55bb080ab",
            "name": "研发大厅",
            "fullName": "湘云大学/大门/研发大厅",
            "description": "",
            "parentId": "8ca8131707c3821645a14f6f19247370",
            "regionLevel": "3",
            "leader": "",
            "sortNo": "",
            "regionType": "1",
            "codeNo": "",
            "roomType": "",
            "campusId": "",
            "parkId": "",
            "functionType": "",
            "longitude": "",
            "latitude": "",
            "planId": "",
            "buildNo": "",
            "floorNo": "",
            "status": "1",
            "openStatus": "2",
            "indexFloor": "",
            "floorCount": "",
            "roomCount": "",
            "label": "",
            "pointName": "",
            "floorCode": "",
            "departId": "",
            "roleId": "",
            "departName": "",
            "openState": "",
            "sections": "",
            "strategyType": "",
            "needRecover": "",
            "managerCount": "",
            "userCount": "",
            "leaf": false
        }
    ],
    pointList: [
        {
            "pointName": "测试教室前门",
            "id": "1e2d81a7b8caa1d72d452e54476fdc7d",
            "regionId": "8ca8131707c3821645a14f6f19247370",
            "pointType": "1",
            "longitude": "",
            "latitude": ""
        },
        {
            "pointName": "测试点位",
            "id": "1e2d81a7b8caa1d72d452e54476fdc7d",
            "regionId": "8ca8131707c3821645a14f6f19247370",
            "pointType": "1",
            "longitude": "",
            "latitude": ""
        }
    ]
})
let pointList = ref([
    {
        "id": "d164bc4477ca47aff8f199dc68c5f18d",
        "pointId": "05B023D85E6424FEE065BF2D21CDB4F8",
        "maplat": "2385.3968253968246",
        "maplon": "1130.3174603174602",
        "pointType": "2",
        "pointName": "销售部202门点"
    },
    {
        "id": "bc331c6dab91ffd4fd47fefb103a6ce6",
        "pointId": "4fa46baf2ec6ad8dcd4d3e5fc5342a8c",
        "maplat": "112",
        "maplon": "728",
        "pointType": "3",
        "pointName": "301教室"
    },
    {
        "id": "3416a0b82a98a2684b81a496359a97ec",
        "pointId": "1e2d81a7b8caa1d72d452e54476fdc7d",
        "maplat": "1934.396825396825",
        "maplon": "1534.8730158730154",
        "pointType": "1",
        "pointName": "测试教室前门"
    },
    {
        "id": "ecd762936ddc13570c10ab1bcc3acfd4",
        "pointId": "c03a4c86b4a6098d3b300016c2f90a09",
        "maplat": "1361.396825396825",
        "maplon": "962.3174603174602",
        "pointType": "1",
        "pointName": "测试教室后门"
    },
    {
        "id": "8b3af1c3f5992095e168db02251979f5",
        "pointId": "32bb8e2f2b85a24b0a4d33ea83134c11",
        "maplat": "1801.3968253968249",
        "maplon": "774.3174603174602",
        "pointType": "2",
        "pointName": "test"
    },
    {
        "id": "7588b3846f5b614658526a35e7cb805d",
        "pointId": "37FC81F282CE4CCAE063DC00A8C06704",
        "maplat": "2603.9999999999995",
        "maplon": "616",
        "pointType": "3",
        "pointName": "6号楼-入口5"
    },
    {
        "id": "f0cfc474098a64a040d03885745175e6",
        "pointId": "7b43c85035ceaeac87b698e55f887258",
        "maplat": "1026",
        "maplon": "1569.9999999999998",
        "pointType": "2",
        "pointName": "讲台摄像头"
    },
    {
        "id": "fe887a88add6bb7bd420dc59b9b7c13c",
        "pointId": "4d5d6a7286ac05508bb6806f0fc16084",
        "maplat": "648",
        "maplon": "362",
        "pointType": "3",
        "pointName": "出口2"
    }
])
function generateNineDigitId() {
    // 生成第一位数字（1-9）
    const firstDigit = Math.floor(Math.random() * 9) + 1;

    // 生成后面八位数字（0-9）
    let remainingDigits = '';
    for (let i = 0; i < 8; i++) {
        remainingDigits += Math.floor(Math.random() * 10);
    }

    // 组合成九位数字ID
    return firstDigit + remainingDigits;
}
interface Tree {
    id?: string
    label: string
    disabled?: boolean
    hasChildren?: boolean
    children?: Tree[]
    value?: string
}
// 选监控或门禁
const selRadio = ref('1')
const searchInput = ref('')
const selRadioList = ref([
    {
        name: '监控点',
        code: '1'
    },
    {
        name: '门禁点',
        code: '2'
    },
    {
        name: '其他点',
        code: '3'
    }
])
watch(selRadio, () => {
    searchInput.value = ''
    dataPage.value = {}
    dataPage.value.pointType = selRadio.value
    // 刷新树结构，key
    treeKey.value++
})
// 结构树
const selCamera: any = ref()
const treeKey = ref(0)
const defaultProps = {
    label: 'name',
    isLeaf: 'leaf',
    number: 'userCount'
}
const dataPage: any = ref({
    pointType: '1'
})

const loadNode = async (node: Node, resolve: (data: Tree[]) => void) => {
    dataPage.value = {
        pointType: selRadio.value
    }
    if (node.level === 0) {
        // const res: any = await GetRigionTreeList(dataPage.value)
        return resolve(ceshiData.value.regionList
        )
    }
    if (node.level > 0) {
        // parentId: node.data.id,
        dataPage.value.regionId = node.data.id
        // const res: any = await GetRigionTreeList(dataPage.value)
        ceshiData.value?.pointList?.forEach((item: any) => {
            item.placeType = 'point'
            item.leaf = true
        })
        ceshiData.value?.regionList?.forEach((item: any) => {
            item.placeType = 'region'
        })
        const showData = [...ceshiData.value.regionList, ...ceshiData.value.pointList]
        console.log(showData)
        return resolve(showData)
    }
}
// 点击点位，图片内的点位也选中
const handleOrgTreeNodeClick = (data: Tree) => {
    selCamera.value = data
    // initMap()
    points.value.forEach((point: any) => {
        point.isSelected = false
    })
    points.value.find((point: any) => point.pointId == data.id).isSelected = true
    drawImage()
}
// 搜索树
const showTree: any = ref(true)
const leftTree: any = ref([])
const searchTree = async () => {
    // if (searchInput.value == '') return
    // showTree.value = false
    // dataPage.value = {
    //     pointType: selRadio.value,
    //     name: searchInput.value
    // }
    // const res: any = await GetRigionTreeList(dataPage.value)
    // res.data?.pointList?.forEach((item: any) => {
    //     item.placeType = 'point'
    //     item.leaf = true
    //     item.parentId = item.regionId
    // })
    // res.data?.regionList?.forEach((item: any) => {
    //     item.placeType = 'region'
    // })
    // const showData1 = [...res.data.regionList, ...res.data.pointList]
    // leftTree.value = buildTree(showData1, '')
}
watch(searchInput, () => {
    if (searchInput.value == '') {
        showTree.value = true
    }
})
// 是否展示选择地图
const isShowMap = ref(false)
const showMap = () => {
    isShowMap.value = !isShowMap.value
}
const clearPoint = () => {
    // ClearPoint(() => {
    //     initMap()
    // })
}
const hideSelMap = () => {
    isShowMap.value = false;
    initMap()
}
provide('hideSelMap', hideSelMap)

// 获取默认地图图片
const image = new Image()
const imageInfo: any = ref({})
const getMap = async () => {
    image.src = map
}
// 获取地图上所有已标记点位
const allPoints: any = ref([])
const copyPoints: any = ref([])
const getAllPoints = async () => {
    allPoints.value = pointList.value
    allPoints.value.forEach((item: any) => {
        item.isSelected = false
        item.maplat = Number(item.maplat)
        item.maplon = Number(item.maplon)
    })
    console.log(allPoints.value)
    copyPoints.value = pointList.value
    points.value = allPoints.value
}

// 画地图！！！
const canvasRef = ref<HTMLCanvasElement | null>(null);
const externalPointRef = ref<HTMLElement | null>(null);
const scale = ref(0.5);
const MIN_SCALE = 0.1;
const MAX_SCALE = 5;
const ZOOM_STEP = 0.05;
// 图片
// 监控点的两种状态
const imagePoint = new Image();
imagePoint.src = point;
const imagePoint2 = new Image(); // 新增第二张点图片对象
imagePoint2.src = pointBlue;
// 门禁点的两种状态
const imageAccess = new Image();
imageAccess.src = access;
const imageAccess2 = new Image();
imageAccess2.src = accessBlue;
// 其他点的两种状态
const otherGrayP = new Image();
otherGrayP.src = otherGray;
const otherBlueP = new Image();
otherBlueP.src = otherBlue;
// 删除图标
const deleteImage = new Image();
deleteImage.src = deleteIcon;
// 新增变量用于记录图片的偏移量
const offsetX = ref(0);
const offsetY = ref(0);
// 记录鼠标按下时的位置
const startX = ref(0);
const startY = ref(0);
// 记录鼠标是否按下
const isDragging = ref(false);
// 记录点是否被拖动
const isPointDragging = ref(false);
// 记录当前拖动点的 id
const draggingPointId = ref<number | null>(null);
// 记录开始点位置
const beforeX: any = ref(0);
const beforeY: any = ref(0);
// 记录结束点位置
const endX: any = ref(0);
const endY: any = ref(0);
// 记录外部点是否正在拖动
const isExternalPointDragging = ref(false);

// 定义要绘制的点的数组，每个点包含 id、maplat、maplon 坐标、半径和是否选中
const points: any = ref([]);
// 提交点数据
const pointData: any = ref({
    pointId: '',
    latitude: '',
    longitude: ''
})
const initMap = () => {
    getMap()
    getAllPoints()
}
/* 
    1.做的地图，点位，路线等产品相关的，都是交给我
    2.首先是分析这个项目的需求，是否缩放，是否有拖动，是否有点击事件，是否要连接路线等等
    3.根据分析需求，去监听canvas的事件，用原生的事件，canvas.addEventListener,例如鼠标点击click，，鼠标滚轮wheel，鼠标拖动(mousemove + mousedown + mouseup)等等（按下事件 => 抬起事件 => 点击事件）（按下事件 => 移动事件 => 抬起事件 => 点击事件）
    4.首先采用的是canvas绘制，将要用到的图片不管是本地的还是接口获取的都转化为图片对象，canvas绘制图片支持引用图片对象
    5.随后就是如何放在canvas画布上展示，要知道绘制顺序靠后的图片会覆盖前面的图片，所以需要将图片按顺序绘制，绘制顺序为：
        1.绘制地图
        2.绘制点位
    6.有时会有需求需要可以缩放绘制的内容，那绘制图片时，就会设置一个缩放比scale,缩放时画布内的内容都要根据缩放比缩放
    7.有时会有拖拽的需求，这种情况可以分为两类，一种是从画布外拖拽到画布内，另一种是将画布内原本的点位或内容拖拽
        1.从画布外拖拽到画布内
        这就要配合鼠标事件了，dragStart和dragEnd函数，这两个函数分别在鼠标按下和抬起时执行，鼠标抬起时记录鼠标在canvas画布内的位置，添加这个点位到点位列表，重新绘制点位，就能在画布内显示这个新增的拖拽点位了
        2.将画布内原本的点位或内容拖拽
        通过监听鼠标事件，当鼠标在画布内移到点位所在位置时，手动将鼠标变为小手，按下后触发先前对canvas加上的click点击事件,给这个点位增加一个标识，就能判断是哪个点位被点击了，也就知道需要拖动哪个点位，当鼠标移动是，就将鼠标相对画布的位置坐标赋值给该点位，也就实现点位的拖动，最后当鼠标松开时，该点位就固定在鼠标的位置上了
*/
const drawImage = () => {
    const canvas = canvasRef.value;
    if (canvas) {
        const ctx = canvas.getContext('2d');
        if (ctx) {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.save();
            ctx.scale(scale.value, scale.value);
            ctx.translate(offsetX.value / scale.value, offsetY.value / scale.value);
            ctx.drawImage(image, 0, 0);

            // 绘制所有点
            points.value.forEach((point: any) => {
                // 判断点图片
                const currentImage = !point.isSelected ? (point.pointType == '1' ? imagePoint : point.pointType == '2' ? imageAccess : point.pointType == '3' ? otherGrayP : otherGrayP) : (point.pointType == '1' ? imagePoint2 : point.pointType == '2' ? imageAccess2 : point.pointType == '3' ? otherBlueP : otherGrayP);

                // 保存当前画布状态
                ctx.save();
                // 恢复到默认缩放比例
                ctx.setTransform(1, 0, 0, 1, 0, 0);

                // 计算点在画布上的实际位置
                const actualX = (point.maplat as number) * scale.value + offsetX.value;
                const actualY = (point.maplon as number) * scale.value + offsetY.value;

                ctx.beginPath();
                // 修改图片绘制尺寸为 26x33
                ctx.drawImage(currentImage, actualX - 13, actualY - 16.5, 26, 33);
                ctx.fill();

                if (point.isSelected) {
                    // 绘制选中框
                    // const boxWidth = 110;
                    const boxWidth = point.pointName.length * 18;
                    const boxHeight = 20;
                    const boxX = actualX - boxWidth / 2;
                    const boxY = actualY - 16.5 - boxHeight - 5;
                    // 定义宽度
                    // let width = point.pointName
                    ctx.fillStyle = 'rgba(13, 15, 19,0.8)';
                    ctx.fillRect(boxX, boxY, boxWidth, boxHeight);

                    // 绘制名字
                    ctx.fillStyle = 'white';
                    ctx.font = '14px Arial';
                    ctx.fillText(point.pointName, boxX + 5, boxY + 15);

                    // 绘制删除图标
                    const iconSize = 13;
                    const iconX = boxX + boxWidth - iconSize - 5;
                    const iconY = boxY + (boxHeight - iconSize) / 2;
                    ctx.drawImage(deleteImage, iconX, iconY, 12, 13);
                }

                // 恢复之前的画布状态
                ctx.restore();
            });
            // 绘制选中框，让他在最上层
            points.value.forEach((point: any) => {
                // 计算点在画布上的实际位置
                const actualX = (point.maplat as number) * scale.value + offsetX.value;
                const actualY = (point.maplon as number) * scale.value + offsetY.value;


                if (point.isSelected) {
                    // 绘制选中框
                    // const boxWidth = 110;
                    const boxWidth = point.pointName.length * 18;
                    const boxHeight = 20;
                    const boxX = actualX - boxWidth / 2;
                    const boxY = actualY - 16.5 - boxHeight - 5;
                    // 定义宽度
                    // let width = point.pointName
                    ctx.fillStyle = 'rgba(13, 15, 19,0.8)';
                    ctx.fillRect(boxX, boxY, boxWidth, boxHeight);

                    // 绘制名字
                    ctx.fillStyle = 'white';
                    ctx.font = '14px Arial';
                    ctx.fillText(point.pointName, boxX + 5, boxY + 15);

                    // 绘制删除图标
                    const iconSize = 13;
                    const iconX = boxX + boxWidth - iconSize - 5;
                    const iconY = boxY + (boxHeight - iconSize) / 2;
                    ctx.drawImage(deleteImage, iconX, iconY, 12, 13);
                }

                // 恢复之前的画布状态
                ctx.restore();
            });
            ctx.restore();
        }
    }
};

const zoomIn = () => {
    if (scale.value < MAX_SCALE) {
        scale.value += ZOOM_STEP;
        drawImage();
    }
};

const zoomOut = () => {
    if (scale.value > MIN_SCALE) {
        scale.value -= ZOOM_STEP;
        drawImage();
    }
};
// 滚轮事件
const handleWheel = (event: WheelEvent) => {
    event.preventDefault();
    const canvas = canvasRef.value;
    if (canvas) {
        const rect = canvas.getBoundingClientRect();
        const mouseX = event.clientX - rect.left;
        const mouseY = event.clientY - rect.top;

        const delta = event.deltaY > 0 ? -ZOOM_STEP : ZOOM_STEP;
        const newScale = scale.value + delta;
        if (newScale >= MIN_SCALE && newScale <= MAX_SCALE) {
            const oldScale = scale.value;
            scale.value = newScale;

            // 计算鼠标在缩放前后的相对位置
            const mouseXRelative = (mouseX - offsetX.value) / oldScale;
            const mouseYRelative = (mouseY - offsetY.value) / oldScale;

            // 根据相对位置调整偏移量
            offsetX.value = mouseX - mouseXRelative * scale.value;
            offsetY.value = mouseY - mouseYRelative * scale.value;

            drawImage();
        }
    }
};

// 处理鼠标按下事件
const handleMouseDown = (event: MouseEvent) => {
    const canvas = canvasRef.value;
    if (canvas) {
        const rect = canvas.getBoundingClientRect();
        const clickX = (event.clientX - rect.left - offsetX.value) / scale.value;
        const clickY = (event.clientY - rect.top - offsetY.value) / scale.value;
        let isPointClicked = false;
        points.value.forEach((point: any) => {
            const imageX = (point.maplat as number) - 13;
            const imageY = (point.maplon as number) - 16.5;
            const imageWidth = 26;
            const imageHeight = 33;

            if (
                clickX >= imageX &&
                clickX <= imageX + imageWidth &&
                clickY >= imageY &&
                clickY <= imageY + imageHeight
            ) {
                isPointDragging.value = true;
                draggingPointId.value = point.id;
                startX.value = clickX;
                startY.value = clickY;
                endX.value = point.maplat;
                endY.value = point.maplon;
                isPointClicked = true;
            }

            // 检查是否点击了删除图标
            if (point.isSelected) {
                const boxWidth = point.pointName.length * 18;
                if (
                    ((boxWidth / 2) - ((clickX - point.maplat) * scale.value)) >= 6 && ((boxWidth / 2) - ((clickX - point.maplat) * scale.value)) <= 22 &&
                    (point.maplon - clickY) * scale.value >= 27 && (point.maplon - clickY) * scale.value <= 41
                ) {
                    // 删除点
                    // DelPoint(point.id, () => {
                    //     initMap()
                    // })
                    pointList.value = pointList.value.filter((p: any) => p.id !== point.id);
                    initMap()
                    ElMessage.success("删除成功");
                    drawImage();
                }
            }
        });

        if (!isPointClicked) {
            // 取消所有点的选中状态
            points.value.forEach((p: any) => p.isSelected = false);
            isDragging.value = true;
            startX.value = event.offsetX;
            startY.value = event.offsetY;
        }

        drawImage();
    }
};

// 处理鼠标移动事件
const handleMouseMove = (event: MouseEvent) => {
    const canvas = canvasRef.value;
    if (canvas) {
        const rect = canvas.getBoundingClientRect();
        const mouseX = (event.clientX - rect.left - offsetX.value) / scale.value;
        const mouseY = (event.clientY - rect.top - offsetY.value) / scale.value;

        let isOverPoint = false;
        points.value.forEach((point: any) => {
            const imageX = (point.maplat as number) - 13;
            const imageY = (point.maplon as number) - 16.5;
            const imageWidth = 26;
            const imageHeight = 33;

            if (
                mouseX >= imageX &&
                mouseX <= imageX + imageWidth &&
                mouseY >= imageY &&
                mouseY <= imageY + imageHeight
            ) {
                isOverPoint = true;
            }
        });

        if (isOverPoint) {
            canvas.style.cursor = 'pointer';
        } else {
            canvas.style.cursor = 'default';
        }

        if (isPointDragging.value) {
            const dx = mouseX - startX.value;
            const dy = mouseY - startY.value;

            const currentPoint = points.value.find((point: any) => point.id === draggingPointId.value);
            beforeX.value = copyPoints.value.find((point: any) => point.id === draggingPointId.value).maplat;
            beforeY.value = copyPoints.value.find((point: any) => point.id === draggingPointId.value).maplon;
            if (currentPoint) {
                // 计算新的点位置
                let newMaplat = (currentPoint.maplat as number) + dx;
                let newMaplon = (currentPoint.maplon as number) + dy;

                // 限制点的位置在图片范围内
                newMaplat = Math.max(13, Math.min(newMaplat, image.width - 13));
                newMaplon = Math.max(16.5, Math.min(newMaplon, image.height - 16.5));

                currentPoint.maplat = newMaplat;
                currentPoint.maplon = newMaplon;

                startX.value = mouseX;
                startY.value = mouseY;
                endX.value = newMaplat;
                endY.value = newMaplon;
                drawImage();
            }
        } else if (isDragging.value) {
            const dx = event.offsetX - startX.value;
            const dy = event.offsetY - startY.value;
            offsetX.value += dx;
            offsetY.value += dy;
            startX.value = event.offsetX;
            startY.value = event.offsetY;
            drawImage();
        }
    }
};

// 处理鼠标松开事件
const handleMouseUp = () => {
    if (draggingPointId.value !== null && endX.value !== 0 && endY.value !== 0) {
        let pointId = points.value.find((point: any) => point.id === draggingPointId.value).pointId
        pointData.value = {
            pointId: pointId,
            latitude: endX.value.toString(),
            longitude: endY.value.toString()
        }
        // pointList.value.push(pointData.value)
        // initMap()
        // AddPoint(pointData.value, () => {  })

    }

    isDragging.value = false;
    isPointDragging.value = false;
    draggingPointId.value = null;
};

// 处理点击事件
const handleClick = (event: MouseEvent) => {
    const canvas = canvasRef.value;
    if (canvas) {
        const rect = canvas.getBoundingClientRect();
        const clickX = (event.clientX - rect.left - offsetX.value) / scale.value;
        const clickY = (event.clientY - rect.top - offsetY.value) / scale.value;

        // 取消所有点的选中状态
        points.value.forEach((p: any) => p.isSelected = false);

        points.value.forEach((point: any) => {
            const imageX = (point.maplat as number) - 13;
            const imageY = (point.maplon as number) - 16.5;
            const imageWidth = 26;
            const imageHeight = 33;

            if (
                clickX >= imageX &&
                clickX <= imageX + imageWidth &&
                clickY >= imageY &&
                clickY <= imageY + imageHeight
            ) {
                // 选中点
                point.isSelected = true;
                drawImage();
            }
        });
    }
};

// 处理外部点拖动开始事件
const handleDragStart = (event: DragEvent, data: any) => {
    // debugger
    isExternalPointDragging.value = true;
    // 设置拖动时的自定义图片
    if (data.pointType == '1') {
        event.dataTransfer?.setDragImage(imagePoint, 13, 16.5);


    } else if (data.pointType == '2') {
        event.dataTransfer?.setDragImage(imageAccess, 13, 16.5);

    } else if (data.pointType == '3') {
        event.dataTransfer?.setDragImage(otherGrayP, 13, 16.5);

    }
};

// 处理外部点拖动结束事件
const handleDragEnd = (event: DragEvent, data: any) => {
    const canvas = canvasRef.value;
    if (canvas) {
        const rect = canvas.getBoundingClientRect();
        if (
            event.clientX >= rect.left &&
            event.clientX <= rect.right &&
            event.clientY >= rect.top &&
            event.clientY <= rect.bottom
        ) {
            const clickX = (event.clientX - rect.left - offsetX.value) / scale.value;
            const clickY = (event.clientY - rect.top - offsetY.value) / scale.value;
            pointData.value = {
                pointId: data.id,
                latitude: clickX.toString(),
                longitude: clickY.toString()
            }
            points.value.push({
                id: generateNineDigitId(),
                isSelected: false,
                maplat: clickX.toString(),
                maplon: clickY.toString(),
                pointId: "05B023D85E6424FEE065BF2D21CDB4F8",
                pointName: "销售部202门点",
                pointType: "2"
            })
            ElMessage.success("添加成功")
            initMap()
            // AddPoint(pointData.value, () => { initMap() })
        }
    }
    isExternalPointDragging.value = false;
};

// 定位函数
const locate = () => {
    const canvas = canvasRef.value;
    if (canvas) {
        // 适当放大，例如放大到 2 倍
        scale.value = 2;
        // 计算图片中心点相对于画布的偏移量
        offsetX.value = (canvas.width / 2 - image.width / 2 * scale.value);
        offsetY.value = (canvas.height / 2 - image.height / 2 * scale.value);
        drawImage();
    }
};
onMounted(() => {
    getMap()
    getAllPoints()
    const canvas = canvasRef.value;
    if (canvas) {
        canvas.addEventListener('wheel', handleWheel);
        canvas.addEventListener('mousedown', handleMouseDown);
        canvas.addEventListener('mousemove', handleMouseMove);
        canvas.addEventListener('mouseup', handleMouseUp);
        canvas.addEventListener('click', handleClick);

        image.onload = () => {
            drawImage();
        };
    }
})
</script>

<style lang="scss" scoped>
.fatherBox {
    :deep(.el-card__body) {
        height: calc(100vh - 16px - 40px - 106px);
        padding: 0;
    }

    .headerBox {
        height: 49px;
        border-bottom: 1px solid #E9E9E9;
        box-sizing: border-box;
        padding: 10px 0 10px 20px;
        display: flex;
        align-items: center;

        span {
            font-size: 16px;
            color: #999999;
        }

        .btn1 {
            margin-left: 15px;
        }

        .btn2 {
            color: #999;
        }
    }

    .contentBox {
        height: calc(100% - 49px);
        overflow: auto;
        display: flex;
        box-sizing: border-box;

        .content-left {
            width: 312px;
            height: 100%;
            box-sizing: border-box;
            padding: 10px;
            border-right: 1px solid #E9E9E9;

            .left-header {
                display: flex;
                flex-direction: column;

                :deep(.el-radio-group) {
                    width: 100%;
                    margin-bottom: 10px;

                    .el-radio-button {
                        width: 33.3%;

                        .el-radio-button__inner {
                            width: 100%;
                            height: 32px;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                        }
                    }
                }

            }

            .left-content {
                height: calc(100% - 84px);
                overflow: auto;
                padding: 10px 0;

                .aside_tree {
                    line-height: 32px;

                    ::v-deep .el-tree-node {
                        .el-tree-node__content {
                            height: 32px;
                            display: block;
                            overflow: hidden;
                            white-space: nowrap;
                            text-overflow: ellipsis;

                            .custom-tree-node {
                                position: relative;

                                img:first-child {
                                    position: absolute;
                                    bottom: 3px;
                                    width: 11px;
                                    height: 13px;
                                }

                                img:last-child {
                                    position: absolute;
                                    width: 10px;
                                    height: 12px;
                                    bottom: 4px;
                                }

                            }
                        }
                    }
                }
            }
        }

        .content-right {
            width: calc(100% - 312px);
            height: 100%;
            box-sizing: border-box;
            position: relative;

            .groupBtn {
                display: flex;
                flex-direction: column;
                position: absolute;
                bottom: 117px;
                right: 10px;

                img {
                    width: 22px;
                    height: 22px;
                }

                .btn1 {
                    width: 32px;
                    height: 32px;
                }

                .btns2 {
                    margin-top: 10px;
                    width: 32px;
                    height: 64px;
                    display: flex;
                    flex-direction: column;

                    .el-button {
                        width: 32px;
                        height: 32px;
                    }

                    .el-button:first-child {
                        border-radius: 4px 4px 0 0;
                        border-bottom: none;
                    }

                    .el-button:last-child {
                        border-radius: 0 0 4px 4px;
                    }
                }
            }
        }
    }
}

.hide {
    width: 0;
    height: 0;
}
</style>